package com.zhl.projectmerger;

import cn.hutool.core.io.FileUtil;
import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.FieldDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;

import java.io.File;
import java.io.FileNotFoundException;

public class JavaSourceCodeMerger implements CodeMerger {
    private JavaSourceCodeMerger() {
    }

    public static class JavaSourceCodeMergerHolder {
        private static final JavaSourceCodeMerger INSTANCE = new JavaSourceCodeMerger();
    }

    public static JavaSourceCodeMerger getInstance() {
        return JavaSourceCodeMergerHolder.INSTANCE;
    }

    private MergerStrategyRegister mergerStrategyRegister = new DefaultMergerStrategyRegister();

    public MergerStrategyRegister getMergerStrategyRegister() {
        return mergerStrategyRegister;
    }

    public void setMergerStrategyRegister(MergerStrategyRegister mergerStrategyRegister) {
        this.mergerStrategyRegister = mergerStrategyRegister;
    }

    /**
     * 合并两个java文件
     *
     * @param mergeFrom
     * @param mergeTo
     * @param mergerConfig
     */
    @Override
    public void merge(File mergeFrom, File mergeTo, ProjectMergeConfig mergerConfig) {
        merge(mergeFrom, mergeTo, mergerConfig, null);
    }

    /**
     * 合并
     * 如果有特殊需求，可以单独调用这个方法，自己指定合并策略
     *
     * @param mergeFrom
     * @param mergeTo
     * @param mergerConfig
     */
    @Override
    public void merge(File mergeFrom, File mergeTo, ProjectMergeConfig mergerConfig, MergeStrategy mergeStrategy) {
        try {
            CompilationUnit from = StaticJavaParser.parse(mergeFrom);
            CompilationUnit to = StaticJavaParser.parse(mergeTo);
            ClassOrInterfaceDeclaration fromClass = from.getClassByName(from.getPrimaryTypeName().orElseThrow(RuntimeException::new)).get();
            ClassOrInterfaceDeclaration toClass = to.getClassByName(to.getPrimaryTypeName().orElseThrow(RuntimeException::new)).get();

            // 1 选择合并策略
            if(mergeStrategy == null) {
                mergeStrategy = mergerStrategyRegister.selectMergeStrategy(fromClass, toClass, mergerConfig);
            }else {
                if (!mergeStrategy.match(fromClass, toClass, mergerConfig)) {
                    throw new RuntimeException("选择的合并策略不匹配");
                }
            }
            if (mergeStrategy == null) {
                // 没有找到合并策略，不做任何处理
                return;
            }

            // 2 import 语句处理
            mergeStrategy.importProcess(from, to);

            // 2 类或接口文件的注解处理
            mergeStrategy.classFileAnnotationProcess(fromClass, toClass);

            // 3 类或接口文件成员处理
            MergeStrategy finalMergeStrategy = mergeStrategy;
            fromClass.getMembers().forEach(memberDeclaration -> {
                if (memberDeclaration instanceof FieldDeclaration) {
                    // 3.1 字段信息处理
                    finalMergeStrategy.fieldsMerge(toClass, (FieldDeclaration) memberDeclaration);
                } else if (memberDeclaration instanceof MethodDeclaration) {
                    // 3.2 方法信息处理
                    finalMergeStrategy.methodMerge(toClass, (MethodDeclaration) memberDeclaration);
                }else if (memberDeclaration instanceof ClassOrInterfaceDeclaration){
                    // 内部类或接口的处理 待实现，如有其它的需求，照抄上面代码添加处理分支
                }
            });

            // 4 输出到源文件
            FileUtil.writeBytes(to.toString().getBytes(),mergeTo);
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
}
